package vn.edu.saigontech.ncms.model.result;

import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import org.hibernate.annotations.OptimisticLockType;

import vn.edu.saigontech.ncms.model.BaseEntity;

@Entity
@org.hibernate.annotations.Entity(dynamicInsert = true, dynamicUpdate = true, optimisticLock = OptimisticLockType.ALL)
@Table(name = "ncms_grade_detail")
@SuppressWarnings("serial")
public class GradeDetail extends BaseEntity {
	@OneToOne
	@JoinColumn(name = "type_id")
	private GradeDetailType gradeDetailType;

	private boolean listening;
	private boolean pronunciation;
	private boolean grammar;
	private boolean reading;
	private boolean writing;
	private boolean speaking;
	private String comment;

	public GradeDetail() {
	}

	/**
	 * inject grades to a specific test
	 * 
	 * @param test
	 * @param listenings
	 * @param speakings
	 * @param grammars
	 * @param readings
	 * @param writings
	 * @param pronunciations
	 * @param index
	 */
	public void injectGrade(AbstractTest test, Double[] listenings,
			Double[] speakings, Double[] grammars, Double[] readings,
			Double[] writings, Double[] pronunciations, int index) {
		if (listening && listenings != null) {
			test.setListening(listenings[index]);
		}
		if (speaking && speakings != null) {
			test.setSpeaking(speakings[index]);
		}
		if (grammar && grammars != null) {
			test.setGrammar(grammars[index]);
		}
		if (reading && readings != null) {
			test.setReading(readings[index]);
		}
		if (writing && writings != null) {
			test.setWriting(writings[index]);
		}
		if (pronunciation && pronunciations != null) {
			test.setPronunciation(pronunciations[index]);
		}
	}
	
	public void injectGrade(AbstractTest test, String[] listenings,
			String[] speakings, String[] grammars, String[] readings,
			String[] writings, String[] pronunciations, int index) {
		if (listening && listenings != null) {
			test.setListening(Double.parseDouble(listenings[index]));
		}
		if (speaking && speakings != null) {
			test.setSpeaking(Double.parseDouble(speakings[index]));
		}
		if (grammar && grammars != null) {
			test.setGrammar(Double.parseDouble(grammars[index]));
		}
		if (reading && readings != null) {
			test.setReading(Double.parseDouble(readings[index]));
		}
		if (writing && writings != null) {
			test.setWriting(Double.parseDouble(writings[index]));
		}
		if (pronunciation && pronunciations != null) {
			test.setPronunciation(Double.parseDouble(pronunciations[index]));
		}
	}

	/**
	 * compute the total written score: listening, grammar, reading, writting,
	 * pronunciation
	 * 
	 * @param test
	 * @return total grade
	 */
	public Double computeTotalWritternScore(AbstractTest test) {
		Double ret = null;
		try {
			if (listening) {
				ret = increase(ret, test.getListening());
			}
			if (grammar) {
				ret = increase(ret, test.getGrammar());
			}
			if (reading) {
				ret = increase(ret, test.getReading());
			}
			if (writing) {
				ret = increase(ret, test.getWriting());
			}
			if (pronunciation) {
				ret = increase(ret, test.getPronunciation());
			}
			return ret;
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return ret;
	}

	/**
	 * increase value of acc depend on input value
	 * 
	 * @param acc
	 * @param value
	 * @return
	 */
	private Double increase(Double acc, Double value) {
		if (value != null) {
			if (acc == null)
				acc = value;
			else
				acc += value;
		}
		return acc;
	}

	/**
	 * check whether all grade has been input
	 * 
	 * @param test
	 * @return
	 */
	public boolean isAllGradeInput(AbstractTest test) {
		boolean ret = true;
		if (listening) {
			ret = checkNull(ret, test.getListening());
		}
		if (grammar) {
			ret = checkNull(ret, test.getGrammar());
		}
		if (reading) {
			ret = checkNull(ret, test.getReading());
		}
		if (writing) {
			ret = checkNull(ret, test.getWriting());
		}
		if (pronunciation) {
			ret = checkNull(ret, test.getPronunciation());
		}
		if (speaking) {
			ret = checkNull(ret, test.getSpeaking());
		}
		return ret;
	}

	private boolean checkNull(boolean acc, Double value) {
		if (value == null)
			acc = false;
		return acc;
	}

	/**
	 * check whether there is any grade has been input from the test
	 * 
	 * @param test
	 * @return
	 */
	public boolean isAnyGradeInput(AbstractTest test) {
		boolean ret = false;
		if (listening) {
			ret = checkNotNull(ret, test.getListening());
		}
		if (grammar) {
			ret = checkNotNull(ret, test.getGrammar());
		}
		if (reading) {
			ret = checkNotNull(ret, test.getReading());
		}
		if (writing) {
			ret = checkNotNull(ret, test.getWriting());
		}
		if (pronunciation) {
			ret = checkNotNull(ret, test.getPronunciation());
		}
		if (speaking) {
			ret = checkNotNull(ret, test.getSpeaking());
		}
		return ret;
	}

	private boolean checkNotNull(boolean acc, Double value) {
		if (value != null)
			acc = true;
		return acc;
	}

	public boolean isListening() {
		return listening;
	}

	public void setListening(boolean listening) {
		this.listening = listening;
	}

	public boolean isGrammar() {
		return grammar;
	}

	public void setGrammar(boolean grammar) {
		this.grammar = grammar;
	}

	public boolean isSpeaking() {
		return speaking;
	}

	public void setSpeaking(boolean speaking) {
		this.speaking = speaking;
	}

	public boolean isReading() {
		return reading;
	}

	public void setReading(boolean reading) {
		this.reading = reading;
	}

	public boolean isWriting() {
		return writing;
	}

	public void setWriting(boolean writing) {
		this.writing = writing;
	}

	public boolean isPronunciation() {
		return pronunciation;
	}

	public void setPronunciation(boolean pronunciation) {
		this.pronunciation = pronunciation;
	}

	public String getComment() {
		return comment;
	}

	public void setComment(String comment) {
		this.comment = comment;
	}

	public GradeDetailType getGradeDetailType() {
		return gradeDetailType;
	}

	public void setGradeDetailType(GradeDetailType gradeDetailType) {
		this.gradeDetailType = gradeDetailType;
	}
}